/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab-modules.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

//===========================================================================================
#include "Ogre_Gfx.h"

//===========================================================================================
dylab::Ogre_Gfx::RayQuery::RayQuery(const String & _name, uint32_t _rayQueryFlags, IScene * _scene, Viewport * _targetViewport, Camera * _usedCamera)
: mName(_name), mTargetViewport(_targetViewport), mUsedCamera(_usedCamera)
{
    // check arguments
    DYLAB_ASSERT(mTargetViewport != NULL);
    DYLAB_ASSERT(mUsedCamera != NULL);

    // create and set up RaySceneQuery result
    mOgreRaySceneQuery = dynamicCast<Scene>(_scene)->getOgreSceneMgr()->createRayQuery(Ogre::Ray(), _rayQueryFlags);
    DYLAB_ASSERT(mOgreRaySceneQuery != NULL);
    mOgreRaySceneQuery->setSortByDistance(true);
}
//-----------------------------------------------------------------------------
dylab::Ogre_Gfx::RayQuery::~RayQuery()
{
}
//-----------------------------------------------------------------------------
dylab::String dylab::Ogre_Gfx::RayQuery::getName() const
{
    return mName;
}
//-----------------------------------------------------------------------------
dylab::Ogre_Gfx::RayQuery::IResult * 
dylab::Ogre_Gfx::RayQuery::execute(uint32_t _screenX, uint32_t _screenY, Vector3 * _intersect)
{
    // store viewport size
    Vector2 vpSize = mTargetViewport->getSize();

    // normalize screen coordinates
    real_t x = static_cast<real_t>(_screenX) / vpSize.x();
    real_t y = static_cast<real_t>(_screenY) / vpSize.y();

    // setup the ray scene query
    Ogre::Ray mouseRay = mUsedCamera->getOgreCamera()->getCameraToViewportRay(x, y);
    mOgreRaySceneQuery->setRay(mouseRay);

    // execute the query
    Ogre::RaySceneQueryResult &result = mOgreRaySceneQuery->execute();
    Ogre::RaySceneQueryResult::iterator it = result.begin();

    // get the first result, if exists
    IResult * iResult = NULL;
    if (it != result.end() && it->movable != NULL)
    {
        // retrieve the result
        iResult = dynamicCast<IResult>(it->movable->getUserObject());

        // obtain the intersection point (on the simulation result bounding box)
        if (_intersect != NULL)        
            *_intersect = toVector3(mouseRay.getPoint(it->distance));        

        // clear the results of the query
        mOgreRaySceneQuery->clearResults();
    }

    // return the intersected result (which could be NULL if no intersection was found)
    return iResult;
}
//-----------------------------------------------------------------------------